<?php
/**
 * @since 05.08.2011
 * @author Akulov Denis <akulov.d.g@gmail.com>
 */
class M_Curd extends MVC_Model_Base {

    private $_strTableWithSettings = '';


    private $_strSource = '';


    private $_strDbName = 'MAIN';


    private $_arOptions = array();


    public function init ($strSource) {
        $this->_strTableWithSettings = $this->getConfig()->getConfig('CURD_TABLE');
        $this->_strSource = $this->_loadTableName($strSource);
        //print_r($this->_strSource);
        $this->_loadOptions();
    }


    /**
     * @param ENUM('of_catalog','to_create', 'to_editing', 'to_remote', 'to_view') $strAction
     * @return boolean
     */
    public function isAccess ($strAction) {
        $mixResult = $this->getOptionsItem('is_access_'.$strAction);
        if (is_null($mixResult)) {
            return false;
        }

        if ($mixResult == 'true') {
            return true;
        }
        return false;
    }


    public function getOptions () {
        return $this->_arOptions;
    }


   public function getNumberOfPages ($arFilter = array()) {
        $objReader = $this->getDbReader($this->_strDbName, $this->_strSource);
        $c = $this->getOptionsItem('number_of_elements_in_page');
        return $objReader->numberOfPagesByFilterArray(intval($c) < 1?10:$c, $arFilter);
    }


    public function getPage (&$iPage, $strSortingBy = '', $arFilter = array()) {

        //print '<pre>'.print_r($this->_arOptions, 1).'</pre>'; die();

        if ($this->getOptionsItem('sorting_in_catalog', $strSortingBy) != 'true') {
            $strSortingBy = '';
        }

        /* TODO just do refactoring WTF???
        $arFilterResult = array();
        foreach ($arFilter as $field => $value) {
            if ($this->_getOptionsItem('enable_filtering', $field)) {
                $arFilterResult[$field] =
                    $this->_getOptions();
            }
        }
        */

        $objReader = $this->getDbReader($this->_strDbName, $this->_strSource);

        $c = $this->getOptionsItem('number_of_elements_in_page');
        return $objReader->pageByFilterArray(
            $iPage,
            (intval($c) > 0)? $c : 10,
            $strSortingBy,
            $arFilter
        );
    }


    public function getOptionsItem ($option, $field = '@all') {
        if (isset($this->_arOptions[$field][$option])) {
            return $this->_arOptions[$field][$option];
        }

        return null;
    }


    public function isShowListOfActions () {
        return $this->isAccess('to_view')    ||
               $this->isAccess('to_editing') ||
               $this->isAccess('to_remote');
    }


    public function element ($id) {
        $dbReader = $this->getDbReader($this->_strDbName, $this->_strSource);
        return $dbReader->element($id);
    }


    public function isExists ($id) {
        $dbReader = $this->getDbReader($this->_strDbName, $this->_strSource);
        return $dbReader->isExists($id);
    }


    public function update ($id, $array) {
        $dbCurd = $this->getDbCurd($this->_strDbName, $this->_strSource);
        $dbCurd->update($id, $array);
    }


    public function create ($array) {
        $dbCurd = $this->getDbCurd($this->_strDbName, $this->_strSource);
        return $dbCurd->create($array);
    }


    public function delete ($id) {
        $dbCurd = $this->getDbCurd($this->_strDbName, $this->_strSource);
        return $dbCurd->delete($id);
    }


    public function getModulesList () {
        $sql = <<<SQL
SELECT S2.value as ARRAY_KEY, S1.*
  FROM  `metacurd_settings` AS S1
  LEFT JOIN  `metacurd_settings` AS S2
    ON S1.table = S2.table AND S2.`option_name` = 'module_title'
  WHERE S1.`option_name` LIKE  'table_alias'
SQL;
        $db = $this->getDb($this->_strDbName);
        return $db->select($sql, $this->_strTableWithSettings);
    }


    public function getFreeTables () {
        $db = $this->getDb($this->_strDbName);

        $sqlGetSettingsTables = <<<SQL
SELECT `table`
  FROM `metacurd_settings`
  GROUP BY `table`
SQL;

        $usedTables = $db->selectCol($sqlGetSettingsTables);

        $sqlGetAllTables = <<<SQL
SHOW FULL TABLES WHERE `Table_type` != 'VIEW'
SQL;

        $allTables = $db->selectCol($sqlGetAllTables);
        return array_diff($allTables, $usedTables);
    }


    public function getFieldsByTable ($strTableName) {
        return $this->getDb($this->_strDbName)->select('SHOW FULL COLUMNS FROM ?# WHERE `Key` != \'PRI\'', $strTableName);
    }


    public function getFields () {
        return $this->getDb($this->_strDbName)->selectCol('SHOW FULL COLUMNS FROM ?#', $this->_strSource);
    }


    public function getFieldsListByTable ($strTableName) {
        return $this->getDb($this->_strDbName)->selectCol('SHOW FULL COLUMNS FROM ?# WHERE `Key` != \'PRI\'', $strTableName);
    }


    public function getAllAccessActionsList () {
        $sql = <<<SQL
SELECT  `name`
FROM  `metacurd_options`
WHERE  `group_name` LIKE  'access_actions'
SQL;
        return $this->getDb($this->_strDbName)->selectCol($sql);
    }


    public function getEditMethods () {
        $strUrl = $this->getConfig()->getAttribute('FW_PATHS', 'PROTOTYPE');
        $strUrl .= 'MVC/V/Curd/FormElement';
        $arResult = scandir($strUrl);
        foreach ($arResult as $k => $item) {
            if (is_dir($strUrl.$item)) {
                unset($arResult[$k]);
                continue;
            }

            if (substr($item, 0, 1) == '.') {
                unset($arResult[$k]);
                continue;
            }

            if (substr($item, -4) != '.php') {
                unset($arResult[$k]);
                continue;
            }

            $arResult[$k] = substr($arResult[$k], 0, strlen($arResult[$k]) - 4);
        }
        return $arResult;
        /*
        return $this->getDb($this->_strDbName)->select(
            'SELECT * FROM `curd_edit_methods`'
        );
        */
    }


    public function commitAdding ($strFullTableName, $arGeneralSettings, $arFieldsSettings) {
        $db = $this->getDb('MAIN');
        $db->transaction();
        try {
            $sqlInsert = <<<SQL
REPLACE INTO ?# SET ?a
SQL;

            $arAccessActions = $this->getAllAccessActionsList();

            foreach ($arGeneralSettings as $options => $value) {
                $arResult = array();
                $arResult['table']   = $strFullTableName;
                $arResult['field']   = '@all';

                if ($options == 'functions') {
                    foreach ($arAccessActions as $action) {
                        $arResult['option_name'] = $action;
                        $arResult['value']   = in_array($action, $value)?'true':'false';

                        $db->query($sqlInsert, $this->_strTableWithSettings, $arResult);
                    }
                    continue;
                }
                $arResult['option_name'] = $options;
                $arResult['value']   = $value;

                $db->query($sqlInsert, $this->_strTableWithSettings, $arResult);
            }

            # 3-е добавляем настройки для полей отдельно
            foreach ($arFieldsSettings as $field => $arSettingsForField) {
                $arResult = array();
                $arResult['table'] = $strFullTableName;
                $arResult['field'] = $field;
                foreach ($arSettingsForField as $options => $value) {
                    if (is_array($value)) {
                        continue;
                    }

                    $arResult['option_name'] = $options;
                    $arResult['value']   = $value;

                    $db->query($sqlInsert, $this->_strTableWithSettings, $arResult);
                }
            }

        } catch (Exception $e) {
            $db->rollback();
            return false;
        }
        $db->commit();
        return true;
    }


    private function _loadTableName ($strShortTableName) {
        $objReader = $this->getDbReader($this->_strDbName, $this->_strTableWithSettings);
        return $objReader->valueBy('table', '`option_name` = \'table_alias\' AND `value` = ?', $strShortTableName);
    }


    private function _loadOptions() {
        $db = $this->getDb($this->_strDbName);
        $sqlGetOptions = <<<SQL
SELECT * FROM ?# WHERE `table` = ?
SQL;
        $this->_strTableWithSettings = 'metacurd_settings';
        $arResult = $db->select($sqlGetOptions, $this->_strTableWithSettings, $this->_strSource);

        $arTmp = array();
        foreach ($arResult as $value) {
            if (empty($value['field'])) {
                $arTmp['@all'][$value['option_name']] = $value['value'];
                continue;
            }
            $arTmp[$value['field']][$value['option_name']] = $value['value'];
        }

        $this->_arOptions = $arTmp;
        return ;
        print '<pre>'.print_r($arTmp, true).'</pre>';
        print '<pre>'.print_r($arResult, true).'</pre>';
        die();
        $this->_arOptions = $db->select(
            'SELECT o.field as ARRAY_KEY1, o.options as ARRAY_KEY2, o.value FROM ?# as o WHERE `table` = ?',
            $this->_strTableWithSettings,
            $this->_strSource
        );
        foreach ($this->_arOptions as $strTable => $arTableOptions) {
            foreach ($arTableOptions as $strOption => $value) {
                $this->_arOptions[$strTable][$strOption] = $this->_arOptions[$strTable][$strOption]['value'];
            };
        }
        $this->_arOptions['@insert_list'] = $this->_parseInsertList();
        print '<pre>'.print_r($this->_arOptions, true).'</pre>';
        die();
    }


    private function _parseInsertList () {
        return explode(';', $this->getOptionsItem('insert_list'));
    }
}